iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Mobile Development

程式初學:Android與Kotlin系列 第 9

Day 9--RecyclerView(二)點擊item

  • 分享至 

  • xImage
  •  

recyclerview有了item的資料列表以後,想要進一步操作,例如點擊
可以如下進行

點擊畫面反饋

在item.xml的屬性加上
android:background="?android:attr/selectableItemBackground"

interface

在Adapter中建立控制點擊的interface,於MainActivity實作後
在ViewHolder實作的OnClick取得欲對其操作的item位置與內容

class RvAdapter(private val listener: OnItemClickListener) :
    RecyclerView.Adapter<RvAdapter.myHolder>() {

    private val list = mutableListOf<Person>()

    inner class myHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {

        val rvName: TextView = itemView.tv_name
        val rvAddress: TextView = itemView.tv_address
        val rvPhone: TextView = itemView.tv_phone

        //      偵測點擊的item,要先放在viewholder class初始化
        init {
            itemView.setOnClickListener(this)
        }
        override fun onClick(v: View?) {
            val position = adapterPosition
            if (position != RecyclerView.NO_POSITION) {
                listener.onItemClick(list[position])
            }
        }
    }

    interface OnItemClickListener {
        fun onItemClick(person: Person)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): myHolder {
        val createView = LayoutInflater.from(parent.context).inflate(
            R.layout.person_item, parent, false
        )
        return myHolder(createView)
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onBindViewHolder(holder: myHolder, position: Int) {
        val currentItem = list[position]
        holder.rvName.text = currentItem.name
        holder.rvAddress.text = currentItem.address
        holder.rvPhone.text = currentItem.phone
    }

    fun update(updateList: List<Person>) {
        list.clear()
        list.addAll(updateList)
        notifyDataSetChanged()
    }
}

實作點擊動作

在MainActivity覆寫interface中的onItemClick方法
例如我們想要點擊item時,把資料帶到dialog做修改動作

class MainActivity : AppCompatActivity(), RvAdapter.OnItemClickListener {

    private val myAdapter = RvAdapter(this)

    private lateinit var db: PersonDatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        db = PersonDatabase.getInstance(this)

        recycler_view.adapter = myAdapter
        recycler_view.layoutManager = LinearLayoutManager(this)

        val dialogItem = LayoutInflater.from(this).inflate(R.layout.dialog, null)
        val confirmButton = dialogItem.findViewById<Button>(R.id.btn_confirm)   //新增
        val deleteButton = dialogItem.findViewById<Button>(R.id.btn_delete)     //刪除
        val cancelButton = dialogItem.findViewById<Button>(R.id.btn_cancel)

        fab.setOnClickListener {
            floatingButton(dialogItem, confirmButton, cancelButton, deleteButton)
        }

        notifyAdapter()
    }

    private fun floatingButton(
        dialogItem: View,
        confirmButton: Button,
        cancelButton: Button,
        deleteButton: Button
    ) {
        val dialogBuilder = AlertDialog.Builder(this@MainActivity)
        val dialog = dialogBuilder
            .setTitle("新增/查詢")
            .setView(dialogItem)
            .setOnDismissListener {
                (dialogItem.parent as ViewGroup).removeView(dialogItem)
            }
            .show()

        confirmButton.setOnClickListener {
            val item = Person(
                dialogItem.ed_name.text.toString(),
                dialogItem.ed_phone.text.toString(),
                dialogItem.ed_address.text.toString()
            )
            if (dialogItem.ed_name.text.isNotEmpty() && dialogItem.ed_phone.text.isNotEmpty()) {
                db.personDataDao.insert(item)
                notifyAdapter()
                dialog.dismiss()
            } else {
                Toast.makeText(this, "請輸入姓名,電話", Toast.LENGTH_SHORT).show()
            }

            dialogItem.ed_name.text.clear()
            dialogItem.ed_phone.text.clear()
            dialogItem.ed_address.text.clear()
        }

        deleteButton.setOnClickListener {
            db.personDataDao.clear()
            notifyAdapter()
            dialog.dismiss()
        }

        cancelButton.setOnClickListener {
            dialogItem.ed_name.text.clear()
            dialogItem.ed_phone.text.clear()
            dialogItem.ed_address.text.clear()
            dialog.dismiss()
        }

    }

//    點擊修改
    override fun onItemClick(person: Person) {
        val dialogUpdate = LayoutInflater.from(this).inflate(R.layout.dialog_update, null)
        val dialogBuilder = AlertDialog.Builder(this@MainActivity)
        val cancelButton = dialogUpdate.findViewById<Button>(R.id.btn_cancel)

        val dialog = dialogBuilder
            .setTitle("修改項目")
            .setView(dialogUpdate)
//      設定當dialog被點掉時,remove原放進來的view(dialogItem),否則再次點fab時會丟exception
            .setOnDismissListener {
                (dialogUpdate.parent as ViewGroup).removeView(dialogUpdate)
            }
            .show()

        dialogUpdate.ed_name.setText(person.name, TextView.BufferType.EDITABLE)
        dialogUpdate.ed_phone.setText(person.phone, TextView.BufferType.EDITABLE)
        dialogUpdate.ed_address.setText(person.address, TextView.BufferType.EDITABLE)

        dialogUpdate.btn_update.setOnClickListener {
            val updateItem = Person(
                dialogUpdate.ed_name.text.toString(),
                dialogUpdate.ed_phone.text.toString(),
                dialogUpdate.ed_address.text.toString(),
                person.personId
            )
            db.personDataDao.update(updateItem)
            notifyAdapter()
            dialog.dismiss()
        }
    }

    private fun notifyAdapter() {
        val itemList = db.personDataDao.getAll()
        myAdapter.update(itemList)
    }
}

這裡發現到一個問題,點擊時,dialog有時有跳出,有時沒有
以爲是app哪裏卡住
請教導師後發現是點在某些view上面的時候不會跳出,認爲應該是view的問題,可開啓開發人員中的show layout bounds(顯示版面配置界限)確認

再針對view檢查問題

果然發現我的TextView裡面有怪怪的屬性android:inputType

<TextView
        ...
        android:inputType="none|number"
        ... />

原來因爲我做輸入的dialog跟顯示的item layout長的差不多,我就將xml內容都複製過來
把標籤EditText改成TextView,以及裡面的id屬性改一下而已,沒注意到其它
既然是TextView,只需要顯示,拿掉android:inputType屬性後
點擊item就都正常了


上一篇
Day 8--RecyclerView(一)簡介
下一篇
Day 10--實作app右上方的menu選單
系列文
程式初學:Android與Kotlin30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言